//
//  BLEOperation.m
//  BLESDKDemo
//
//  Created by 李阳 on 2018/5/2.
//  Copyright © 2018年 李阳. All rights reserved.
//

#import "BLEOperation.h"
#import "NSError+BLEAdd.h"

@interface BLEOperation ()

/// 需要更新的通知特征名称
@property (nonatomic, copy) NSArray<NSString *>* needUpdateNotifyValueCharacteristicNames;

/// 定时器
@property (nonatomic, strong) NSTimer *timer;

/// 开始操作时的时间戳
@property (nonatomic, assign) NSTimeInterval begin;
/// 结束操作时的时间戳
@property (nonatomic, assign) NSTimeInterval end;
/// 创建时的时间戳
@property (nonatomic, assign) NSTimeInterval born;

/// 错误
@property (nonatomic, strong) NSError *error;

@end

@implementation BLEOperation

#pragma mark - Public

- (void)scheduleWithObject:(id)object
{
    if (!_hasFired)
    {
        return;
    }
    if (!_timer.isValid)
    {
        return;
    }
    _end = [[NSDate date]timeIntervalSince1970];
    NSTimeInterval interval = _end - _begin;
    !_scheduleBlock ?: _scheduleBlock(self, interval, object);
}

- (void)fire
{
    if (!_timer)
    {
        [self start];
    }
    _hasFired = YES;
    _begin = [[NSDate date] timeIntervalSince1970];
    !self.fireBlock ?: self.fireBlock(self, _begin - _born);
}

/// 开始定时器
- (void)start
{
    if (_timeout <= 0)
    {
        NSString *reason = [NSString stringWithFormat:@"_timeout %lf is invalid", _timeout];
        @throw [NSException exceptionWithName:NSInvalidArgumentException reason:reason userInfo:nil];
        return;
    }
    [[NSRunLoop currentRunLoop]addTimer:self.timer forMode:NSRunLoopCommonModes];
}

- (void)invalidate
{
    [_timer invalidate];
    _timer = nil;
    _fireBlock = nil;
    _end = [[NSDate date]timeIntervalSince1970];
    NSTimeInterval interval = _end - (_begin ?: _born);
    !_invalidateBlock ?: _invalidateBlock(self, interval, self.error);
    _invalidateBlock = nil;
    _scheduleBlock = nil;
}

- (void)invalidateWithError:(NSError *)error
{
    self.error = error;
    [self invalidate];
}

#pragma mark - Action

- (void)timeoutAction
{
    self.error = [NSError bleTimeoutError];
    [self invalidate];
}

#pragma mark - Getter

- (NSTimer *)timer
{
    if (_timeout <= 0) return nil;
    if (_timer) return _timer;
    _timer = [NSTimer timerWithTimeInterval:_timeout target:self selector:@selector(timeoutAction) userInfo:nil repeats:NO];
    return _timer;
}

#pragma mark - Setter

- (void)setType:(BLEOperationType)type
{
    _type = type;
    if (_timeout > 0)
    {
        /// 已经设置过超时时间
        return;
    }
    switch (type) {
        case BLEOperationTypeIdle:
        {
            _timeout = 0;
        }
            break;
        case BLEOperationTypeSearch:
        {
            _timeout = 10;
        }
            break;
        case BLEOperationTypeConnect:
        {
            _timeout = 10;
        }
            break;
        case BLEOperationTypeDisconnect:
        {
            _timeout = 10;
        }
            break;
        case BLEOperationTypeReadRSSI:
        {
            _timeout = 10;
        }
            break;
        case BLEOperationTypePrepareSession:
        {
            _timeout = 10;
        }
            break;
        case BLEOperationTypeSession:
        {
            _timeout = 10;
        }
            break;
    }
}

#pragma mark - NSObject


- (BOOL)isEqualToOperation:(BLEOperation *)op
{
    return (_type == op.type) && (_timeout == op.timeout);
}

- (BOOL)isEqual:(id)object
{
    if (self == object) return YES;
    if (![object isKindOfClass:[self class]]) return NO;
    return [self isEqualToOperation:object];
}

- (NSUInteger)hash
{
    return _type;
}


#pragma mark - Lifecyle

- (instancetype)init
{
    self = [super init];
    if (!self) return nil;
    _born = [NSDate date].timeIntervalSince1970;
    return self;
}

- (void)dealloc
{
    [self invalidate];
}

@end
